namespace Patterns4Net.PatternEnforcer.Core
{
    using System.Collections.Generic;
    using System.Diagnostics.Contracts;
    using System.Linq;
    using Attributes.DesignPatterns;

    /// <summary>
    /// Represents a composition of several checkers.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    [Immutable]
    [Composite(Component = typeof(IChecker<>))]
    public class CompositeChecker<T> : IChecker<T> where T : class
    {
        private readonly IEnumerable<IChecker<T>> checkers;

        public CompositeChecker(IEnumerable<IChecker<T>> classCheckers)
        {
            Contract.Requires(classCheckers != null);
            Contract.Requires(Contract.ForAll(classCheckers, x => x != null));
            Contract.Ensures(Contract.ForAll(this.checkers, x => x != null));
            this.checkers = classCheckers.ToArray(); // Copy them
        }

        public CheckerResult Check(T subject)
        {
            var results = this.checkers.Select(classChecker => classChecker.Check(subject)).ToArray(); // we dont need lazy eval
            return new CheckerResult(results);
        }

        [ContractInvariantMethod]
        private void CheckersNotNull()
        {
            Contract.Invariant(this.checkers != null);
            Contract.Invariant(Contract.ForAll(this.checkers, x => x != null));
        }
    }
}
